*
preproot jsr findvol ;search vcb's and devices for specified volume.
 bcs novolume ;branch if not found.
 lda #0 ;zero out directory temps.
 ldy #$42 ; 
clrdsp sta own.blok,y ;and owner info. 
 dey
 bpl clrdsp
 lda devnum ;set up device number for this directory.
 sta d.dev
 jsr movhed0 ;set up other header info from directory in gbuf.
 ldy #1 ;and clean up misc.
 ldx vcbptr
 inx
rootmisc lda vcb+vcbtblk,x ;misc info includes
 sta h.tblk,y ;total # of blocks,
 lda vcb+vcbdmap,x ; the address of the first bitmap
 sta h.bmap,y 
 lda bloknml,y ;and directory's disk address, 
 sta d.head,y
 lda h.fcnt,y ;and lastly, setting up a counter for the number of
 sta entcntl,y ; files in this directory.
 dex ;move low order bytes too.
 dey
 bpl rootmisc
*
nxtpname jsr nxtpnam1 ;get new pnptr in y and next namlen in acc.
 sty pnptr ;save new pathname pointer.
 rts ;(status reg according to accumulator)
*
nxtpnam1 ldy pnptr ;bump pathname pointer to next name
 lda pathbuf,y ; in the path...
 sec 
 adc pnptr ;if this addition results in zero,
 tay ; then prefixed directory has been moved to
 bne nxpnmret ; another device. branch if not.
 lda devnum ;revise devnum for prefixed directory
 sta p.dev
nxpnmret lda pathbuf,y ;test for end of name. 
 clc ;indicate no errors. 
novolume rts
*
*
findvol lda #0
 ldy pfixptr ;use prefix volume name to look up vcb.
 bit prfxflg ;is this a prefixed path?
 bpl fndvol2 ;branch in it is. 
*
fndvol1 tay ;set ptr to volume name.
fndvol2 sty vnptr ;save pointer.
 sta devnum ;zero out device number until vcb located.
fndvol3 pha ;acc now used as vcb lookup index
 tax ;move pointer to x for index.
 lda vcb,x ;get vcb volume name length
 bne matchvol ;branch if claimed vcb to be tested.
nxtvcb ldy vnptr ;restore ptr to reqested volume name.
 pla ;now adjust vcb index to next vcb entry.
 clc
 adc #$20
 bcc fndvol3 ;branch if more vcb's to check.
 bcs lookvol ;otherwise go look for unlogged volumes.
*
matchvol sta namcnt ;save length of vol name to be compared
mtchvol1 cmp pathbuf,y ;is it the same as requested vol name?
 bne nxtvcb ;branch if not.
 inx
 iny ;bump to next character
 lda vcb,x
 dec namcnt ;was that the last character?
 bpl mtchvol1 ;branch if not.
*
 pla ;restore pointer to vcb that matches.
 tax
 sta vcbptr ;save it for future reference.
 lda vcb+vcbdev,x ;get its device number
 sta devnum ;save it.
 lda #$00 ; assume prefix is not used and
 sta bloknmh ; that root directory is to be used.
 lda #$02     
 sta bloknml
 lda vnptr ;= 0 if no prefix. 
pfxdir tay ;if prefix, then find ptr to prefixed dir name.
 sta pnptr ;save path ptr.
 beq fndvol4 ;branch if no prefix. 
 sec ;bump to next dir in prefix path
 adc pathbuf,y
 bcc pfxdir ;branch if there is another dir in prefix.
 lda p.blok ;volume verification will occur at
 sta bloknml ; sub directory level.
 lda p.blok+1
 sta bloknmh
*
******verify volume name****** 
*
fndvol4 jsr rdgbuf ;read in directory (or prefix directory)
 bcs wrgvol ;if error then look on other devices
 jsr cmppnam ;compare directory name with pathname
 bcc wrg7 ;if they match, don't look elswhere.
*
wrgvol ldx vcbptr ;find out if current (matched) vcb is active.
 lda vcb+vcbstat,x ; i.e. does it have open files?
 bmi lvolerr ;report not found if active.
*
lookvol lda vnptr ;make path pointer same as volume ptr.
 sta pnptr
 jsr mvdevnums ;copy all device numbers to be examined.
 lda devnum ;log current device first, before searching others
 bne wrg3 
wrg1 ldx devcnt ;scan look list for devices we need
wrg2 lda loklst,x ; to search for the requested volume.
 bne wrg4 ;branch if we've a device to look at.
 dex
 bpl wrg2 ;look at next guy.
lvolerr lda #vnferr ;report that no mounted volume
 sec ; matches the requested.
wrg7 rts
*
wrg3 ldx devcnt ;now remove the device from the list
wrg4 cmp loklst,x ; of prospective devices (so we don't look twice)
 beq wrg5 ;branch if match.
 dex ;look until found.
 bpl wrg4 ;branch always taken! (usually!) * * *
* -------------------- see rev note 16 -----------------------------
 bmi lvolerr ;never unless device was manually removed from devlst (/ram)
* ------------------------------------------------------------------
*
wrg5 sta devnum ;preserve dedice we're about to investigate.
 lda #0
 sta loklst,x ;mark this one as tested.
 jsr fnddvcb ;find vcb that claims this device, if any.
 bcs fnvolerr ;branch if vcb full.
 ldx vcbptr ;did 'fnddvcb' find it or did it return free vcb?
 lda vcb,x
 beq wrg6 ;branch if free vcb.
 lda vcb+vcbstat,x ;is this volume active?
 bmi wrg1 ;if so, no need to re-log.
wrg6 lda #2 ;go read root directory into gbuf.
 ldx #0
 jsr rdblk
 bcs wrg1 ;ignore if unable to read.
 jsr logvcb ;go log in this volume's proper name.
 bcs wrg1 ;look at next if non xdos disk was mounted.
 jsr cmppnam ;is this the volume we're looking for?
 bcs wrg1 ;branch if not.
fnvolerr rts ;return to caller. 
*
mvdevnums ldx devcnt ;copy all device numbers to be examined.
mvdvnum1 lda devlst,x
 and #$f0 ;strip device type info.
 sta loklst,x ;copy them to a temporary workspace.
 dex
 bpl mvdvnum1 
 ldx devcnt
 rts
*
fnddvcb lda #0 ;look for vcb with this device number.
 ldy #$ff
fddvcb tax ;new index to next vcb.
 lda vcb+vcbdev,x ;check all devnums.
 cmp devnum ;is this the vcb were looking for?
 bne fnxtvcb ;branch if not.
 stx vcbptr
 clc ;indicate found.
 rts
fnxtvcb lda vcb,x ;is this a free vcb? 
 bne fnxvcb1 ;branch if not.
 iny
 stx vcbptr
fnxvcb1 txa ;now...
 clc ;bump index to next vcb.
 adc #$20
 bne fddvcb
 tya ;were any free vcb's available?
 bmi vfulerr ;branch if not.
 clc ;indicate no errors
vfulerr lda #vcbfull
 rts
*
cmppnam ldx #0 ;index to directory name.
 ldy pnptr ;index to pathname
 lda gbuf+4 ;get directory name length (and type)
 cmp #$e0 ;also make sure it's a directory
 bcc vnocmp ;branch if not a directory.
 and #$f ;isolate name length
 sta namcnt ;save as counter.
 bne cmpvnm1 ;branch if valid length
vnocmp sec ;indicate not what were looking for.
 rts 
cmpvnm0 lda gbuf+4,x ;get next char.
cmpvnm1 cmp pathbuf,y
 bne vnocmp ;branch if not the same.
 inx ;chek nxt char.
 iny
 dec namcnt
 bpl cmpvnm0 ;branch if more to compare.
 clc ;otherwise we got a match!!!
 rts
*
logvcb ldx vcbptr ;is this a previously logged in volume
 lda vcb,x ;(acc=0?)
 beq logvcb1 ;no, go ahead and prepare vcb.
 jsr cmpvcb ;does vcb match volume read?
 bcc vcblogd ;yes, don't disturb it.
*
logvcb1 lda #0 ;zero out vcb entry
 ldy #vcbsize-1
zervcb sta vcb,x 
 inx
 dey
 bpl zervcb
 jsr tstsos ;make sure it's an xdos diskette.
 bcs vcblogd ;if not, return carry set.
 jsr tstdupvol ;find out if a duplicate with open files already exists
 bcs notlog0 
 lda gbuf+4 ;move volume name to vcb
 and #$f ;strip root marker
 tay
 pha
 ora vcbptr
 tax
movolnm lda gbuf+4,y
 sta vcb,x 
 dex
 dey
 bne movolnm
 pla ;get length again
 sta vcb,x ;save that too.
 lda devnum
 sta vcb+vcbdev,x ;save device number also. 
 lda gbuf+vtblk+4 ;and totol number of blocks on this unit,
 sta vcb+vcbtblk,x 
 lda gbuf+vtblk+5
 sta vcb+vcbtblk+1,x 
 lda bloknml ;and address of root directory
 sta vcb+vcbroot,x 
 lda bloknmh
 sta vcb+vcbroot+1,x 
 lda gbuf+vbmap+4 ;and lastly, the address
 sta vcb+vcbdmap,x ; of the first bitmap
 lda gbuf+vbmap+5
 sta vcb+vcbdmap+1,x 
notlog0 clc ;indicate that it was logged if posible. 
vcblogd rts
*
cmpvcb lda gbuf+4 ;compare volume name in vcb
 and #$f ; with name in directory
 cmp vcb,x ;are they same length
* -------------------- see rev note 23 --------------------
 stx xvcbptr
* -----------------------------------------------------------
 bne notsam1 
 tay
 ora xvcbptr 
 tax
vcbcmp1 lda gbuf+4,y
 cmp vcb,x 
notsam1 sec ;anticipate different names
 bne notsame
 dex
 dey
 bne vcbcmp1
 clc ;indicate match.
notsame equ *
* -------------------- see rev note 23 --------------------
 ldx xvcbptr ;get back offset to start of vcb
* -----------------------------------------------------------
 rts
*
tstdupvol lda #0 ;look for other logged in volumes with same name. 
tsdupv1 tax 
 jsr cmpvcb
 bcs tsdupv2 ;branch if no match.
 lda vcb+vcbstat,x ;test for any open files 
 bmi founddup ;tell the sucker he can't look at this volume!
 lda #0 ;take duplicate off line if no open files.
 sta vcb,x 
 sta vcb+vcbdev,x
 beq nodupvol ;return that all is ok to log in new.
*
tsdupv2 txa ;index to next vcb
 clc
 and #$e0 ;strip odd stuff.
 adc #vcbsize ;bump to next entry.
 bcc tsdupv1 ;branch if more to look at. 
*
nodupvol clc
 rts
*
founddup sta duplflag ;a duplicate has been detected.
 stx vcbentry ;save pointer to conflicting vcb.
 sec ;indicate error
 rts 
 page
*
tsfrblk ldx vcbptr ;find out if enough free blocks 
 lda vcb+vcbtfre+1,x ;available to accomdate the request. 
 ora vcb+vcbtfre,x ;but first find out if we got a proper count for this volume.
 bne cmpfreb ;branch if count is non-zero
tkfrecnt jsr cntbms ;get # of bitmaps. 
 sta bmcnt ;save it.
 lda #0 ;start count at zero.
 sta scrtch
 sta scrtch+1
 lda #$ff ;mark 'first free' temp as unknown
 sta nofree
 jsr upbmap ;(nothing happens if it don't hafta.)
 bcs tfberr ;branch if we got trouble,
 ldx vcbptr ;get address of first bit map.
 lda vcb+vcbdmap,x 
 sta bloknml
 lda vcb+vcbdmap+1,x 
 sta bloknmh
bmaprd jsr rdgbuf ;use g(eneral)buff(er) for temporary
 bcs tfberr ; space to count free blocks (bits)
 jsr count ;go count em
 dec bmcnt ;was that the last bit map?
 bmi chgvcb ;if so, go change fcb to avoid doing this again!
 inc bloknml ;note: the organization of the bit maps
 bne bmaprd ; are contiguous for sos version 0
 inc bloknmh ; if some other organization is implemented, this code
 jmp bmaprd ; must be changed! 
 page
*
chgvcb ldx vcbptr ;mark which block had first free space
 lda nofree
 bmi dskfull ;branch if no free space was found.
 sta vcb+vcbcmap,x ;update the free count.
 lda scrtch+1 ;get high count byte
 sta vcb+vcbtfre+1,x ;update volume control block.
 lda scrtch
 sta vcb+vcbtfre,x ;and low byte too...
cmpfreb lda vcb+vcbtfre,x ;compare total available
 sec
 sbc reql ; free blocks on this volume.
 lda vcb+vcbtfre+1,x 
 sbc reqh
 bcc dskfull
 clc
 rts
dskfull lda #ovrerr 
 sec
tfberr rts
 page
*
count ldy #0 ;begin at the beginning.
frcont lda gbuf,y ;get bit pattern
 beq frcnt1 ;don't bother counting nothin'
 jsr cntfree
frcnt1 lda gbuf+$100,y ;do both pages with same loop
 beq frcnt2
 jsr cntfree
frcnt2 iny
 bne frcont ;loop till all 512 bytes counted
 bit nofree ;has first block with free space been found yet?
 bpl frcnt3 ;branch if it has.
 lda scrtch ;test to see if any blocks were counted
 ora scrtch+1
 beq frcnt3 ;branch if none counted.
 jsr cntbms ;get total # of maps. 
 sec ;subtract countdown from total bit maps
 sbc bmcnt
 sta nofree
frcnt3 rts
*
cntfree asl a ;count the number of bits in this byte.
 bcc cfree1
 inc scrtch
 bne cfree1
 inc scrtch+1
cfree1 ora #0 
 bne cntfree ;loop until all bits counted.
 rts
*
cntbms ldx vcbptr 
 ldy vcb+vcbtblk+1,x ;return the # of bit maps 
 lda vcb+vcbtblk,x ; posible with the total count 
 bne cntbms1 ; found in the vcb... 
 dey ; adjust for bitmap block boundary
cntbms1 tya
 lsr a ;divide by 16. the result is the number
 lsr a ; of bit maps.
 lsr a
 lsr a
 rts
*
